package cn.dansj.controller;

import cn.dansj.common.request.annotation.http.GetMethod;
import cn.dansj.common.request.annotation.http.PostMethod;
import cn.dansj.common.request.annotation.http.RequestMappingMethod;
import cn.dansj.common.request.annotation.http.RequestParam;
import cn.dansj.common.utils.bean.CacheToken;
import cn.dansj.common.utils.json.DictMap;
import cn.dansj.common.request.RequestUtils;
import cn.dansj.common.redis.RedisUtils;
import cn.dansj.common.utils.transfer.Verification;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import cn.dansj.entity.Menu;
import cn.dansj.service.MenuService;
import cn.dansj.common.utils.transfer.GetTime;
import cn.dansj.common.utils.bean.Return;
import cn.dansj.enums.GlobalEnv;
import cn.dansj.common.utils.transfer.Transformation;
import cn.dansj.utils.project.ProjectUtils;

import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

@RequestMappingMethod("/menu")
public class MenuController {
    private final MenuService menuService;
    private final RedisUtils redisUtils;

    public MenuController(MenuService menuService, RedisUtils redisUtils) {
        this.menuService = menuService;
        this.redisUtils = redisUtils;
    }

    /*
     * 加载管理员的左侧菜单及路由信息
     * */
    @GetMethod("/getMenu")
    public Return<?> getSideMenu(CacheToken cacheToken) {
        List<Menu> menus;
        if (GlobalEnv.Admin.equals(cacheToken.getUsername()) || (GlobalEnv.SuperAdmin.equals(cacheToken.getRole()))) {
            final String menuString = redisUtils.getString("menu");
            menus = JSON.isValidArray(menuString) ? DictMap.parseObject(menuString, new DictMap.JavaType<>() {
            }) : menuService.getMenu();
        } else {
            menus = menuService.getRoleMenu(cacheToken.getRole());
        }
        final List<Menu> rootMenus = menus.stream().filter(e -> Verification.checkNull(e.getParentId())).collect(Collectors.toList());
        final List<String> rootSequences = rootMenus.stream().map(Menu::getSequence).toList();

        List<Menu> router = menus.stream().filter(e -> !rootSequences.contains(e.getSequence())).collect(Collectors.toList());

        //加载目录结构
        for (Menu rootMenu : rootMenus) {
            List<Menu> children = rootMenu.getChildren();
            String rootSequence = rootMenu.getSequence();
            for (Menu menu : menus) {
                String parentId = menu.getParentId();
                if (rootSequence.equals(parentId)) {
                    children.add(menu);
                }
            }
        }
        if (Verification.checkAllNull(router, rootMenus)) {
            return RequestUtils.response401("无权限访问系统");
        }
        return Return.T(DictMap.of("menu", rootMenus, "router", router));
    }

    /*
     * 菜单设置的显示项
     * */
    @GetMethod("/getMenuTree")
    public Return<?> getMenuTree() {
        List<Menu> menus = menuService.getMenu();
        final List<Menu> rootMenus = menus.stream().filter(e -> Verification.checkNull(e.getParentId())).collect(Collectors.toList());

        //加载目录结构
        for (Menu rootMenu : rootMenus) {
            List<Menu> children = rootMenu.getChildren();
            String rootSequence = rootMenu.getSequence();
            for (Menu menu : menus) {
                String parentId = menu.getParentId();
                if (rootSequence.equals(parentId)) {
                    children.add(menu);
                }
            }
        }
        return Return.T(rootMenus);
    }

    @PostMethod("/saveMenu")
    public Return<?> saveMenu(@RequestParam JSONObject request) {
        boolean batchCommit = request.getBooleanValue("batchCommit");
        Timestamp nowTime = GetTime.dbTimestamp();
        List<Menu> menuList = new ArrayList<>();
        if (batchCommit) {
            JSONArray menuData = request.getJSONArray("data");
            //父节点排序
            int parentRowNumber = 0;
            for (Object obj : menuData) {
                Menu parentMenu = DictMap.parseObject(obj, Menu.class);
                //设置父节点的parent_id为空
                parentMenu.setParentId(null);
                //重新设置父节点的排序
                parentMenu.setRn(parentRowNumber);
                //子节点排序
                int childRowNumber = 0;
                for (Menu childMenu : parentMenu.getChildren()) {
                    //设置子节点的parent_id为父节点的编号
                    childMenu.setParentId(parentMenu.getSequence());
                    //重新设置子节点的排序
                    childMenu.setRn(childRowNumber);
                    //如果节点的创建时间为空,则说明节点是新增节点,设置对应的创建时间和更新时间
                    if (childMenu.getCrtTime() == null) {
                        childMenu.setCrtTime(nowTime);
                    }
                    childMenu.setUpdateTime(nowTime);
                    childMenu.setPermission(Transformation.nvl(ProjectUtils.transferMenuPermission(childMenu.getPermission()), Menu.defaultPermission));
                    menuList.add(childMenu);
                    childRowNumber += 1;
                }
                //如果节点的创建时间为空,则说明节点是新增节点,设置对应的创建时间和更新时间
                if (parentMenu.getCrtTime() == null) {
                    parentMenu.setCrtTime(nowTime);
                }
                parentMenu.setUpdateTime(nowTime);
                parentMenu.setPermission(Transformation.nvl(ProjectUtils.transferMenuPermission(parentMenu.getPermission()), Menu.defaultPermission));
                menuList.add(parentMenu);
                parentRowNumber += 1;
            }
        } else {
            Menu menu = request.getObject("data", Menu.class);
            List<String> permission = JSON.parseArray(request.getJSONObject("data").getJSONArray("permission").toJSONString(), String.class);
            menu.setPermission(String.join(",", permission));
            menu.setUpdateTime(nowTime);
            if (menu.getCrtTime() == null) {
                menu.setCrtTime(nowTime);
            }
            menuList.add(menu);
        }

        try {
            menuService.save(menuList);
            GlobalEnv.threadPool.execute(menuService::getMenu);
            return Return.T(true, "提交成功");
        } catch (Exception e) {
            return Return.T(false, "提交失败");
        }
    }

    @PostMethod("/delMenu")
    public Return<?> modifyMenu(@RequestParam JSONObject request) {
        try {
            menuService.delMenu(request.getObject("data", Menu.class));
            return Return.T(true, "节点删除成功");
        } catch (Exception e) {
            return Return.T(false, "节点删除失败");
        }
    }
}
